package aquarium.items;

import java.awt.Image;
import java.awt.Point;
import java.util.Collection;
import java.util.Iterator;
import java.util.Stack;

import aquarium.gui.Aquarium;
import aquarium.move.Mobile;
import aquarium.time.TManager;
import aquarium.time.TimerKind;
import aquarium.util.RandomNumber;

public abstract class MobileItem extends AquariumItem implements Mobile {

	private Point _target;

	private static int _TIME_FECOND = 100;
	private static int _BUBBLE_PERCENT = 1;

	private boolean _visitor;

	public MobileItem(Image image, 
			Point position, 
			int size,
			boolean destructible, 
			boolean letal, 
			long move_delay,
			long change_target_delay,
			Point target,
			boolean visitor,
			TManager tmanager) {
		super(image, position, size, destructible, letal, move_delay, tmanager);
		this._target = target;
		this._visitor = visitor;
		if (tmanager != null && change_target_delay > 0)
			tmanager.addObserver(this, TimerKind.Target, change_target_delay);
	}

	public boolean is_visitor(){
		return _visitor;
	}

	public void set_visitor(){
		_visitor = true;
	}


	public void update(TimerKind kind, Collection<AquariumItem> items, Aquarium aquarium) { //kind = position ou target
		if (kind == TimerKind.Target) { // Si target
			(this).newTarget(items);
		} 

		else if (kind == TimerKind.Position) { //Si position

			if (_target.equals(get_position()))  // Verifie que le poisson est a destination 
				(this).newTarget(items); // Change de target si c'est le cas
			move(items);
			dead(items); // On vérifie les poissons mort

			bubble(aquarium, items);

			if(this instanceof Fish){
				((Fish)this).set_fecond(((Fish)this).get_fecond()+1);
				if( ((Fish)this).get_fecond() >= _TIME_FECOND && this instanceof Fish){
					aquarium.add_egg();
					((Fish)this).set_fecond(0);
				}
			}
		}
	}

	private void bubble(Aquarium aquarium, Collection<AquariumItem> items){
		if(this instanceof Fish){
			Collection<AquariumItem> tmp = aquarium.getCollection();
			Stack<AquariumItem> pile = new Stack<AquariumItem>();
			synchronized(tmp){
				Iterator<AquariumItem> it = tmp.iterator();
				while (it.hasNext()) 
				{
					AquariumItem ai = it.next();
					if (ai instanceof Fish){
						if(RandomNumber.randomValue(0, 5000) < _BUBBLE_PERCENT){
							pile.push(this);
							pile.push(ai);
						}
					}
				}
				while(!pile.empty()){
					AquariumItem fish_victim = pile.pop();
					AquariumItem fish_killer = pile.pop();
					if (!fish_victim.equals(fish_killer) && !((Fish)fish_killer).is_piscivore())
						aquarium.creat_bubble(fish_killer, fish_victim);
				}
			}
		}
	}

	// Déplacement vers une destination donnée
	public void move(Collection<AquariumItem> neighbours) {
		if(!_target.equals(get_position())) {
			int v = (100/this.get_size())+1;
			int dx = (_target.x-this.get_position().x);
			int dy = (_target.y-this.get_position().y);
			int dist = (int)Math.sqrt(dx*dx+dy*dy);
			int modx = v*dx/dist;
			int mody = v*dy/dist;

			if (Math.abs(modx) > Math.abs(dx))
				modx = dx;

			if (Math.abs(mody) > Math.abs(dy))
				mody = dy;

			Point p = this.get_position();
			p.translate(modx,mody);
			this.set_position(p);
		}
	}

	public Point get_target() {
		return _target;
	}

	public void set_target(Point target) {
		this._target = target;
	}

	public void newTarget(Collection<AquariumItem> items){

	}
}
